#include "app_misc.h"
#include "app_config.h"
#include "app_sys.h"
#include <stdint.h>
#include "sys_manager.h"
#include "drv_sys.h"

/***
 * Buzzer
 */

#define Buzzer_Pin GPIO_PIN_4
#define Buzzer_GPIO_Port GPIOB
#define app_fm_pin GPIO_PIN_5
#define app_fm_gpio_port GPIOB

// 蜂鸣器启动（输出低电平）
void app_buzzer_start(void)
{
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_RESET);
}

// 蜂鸣器停止（输出高电平）
void app_buzzer_stop(void)
{
    HAL_GPIO_WritePin(Buzzer_GPIO_Port, Buzzer_Pin, GPIO_PIN_SET);
}

// 定义设置蜂鸣器触发的函数
void app_buzzer_trigger(uint16_t duration_ms)
{
    app_buzzer_start();
    system_status.user.buzzer_state = 1;       // 设置蜂鸣器开启状态
    system_status.user.buzzer_timer = duration_ms; // 设置蜂鸣器触发时长（单位：毫秒）
}

// 继电器（输出高电平）
void app_fm_start(void)
{
    HAL_GPIO_WritePin(app_fm_gpio_port, app_fm_pin, GPIO_PIN_SET);
}

// 继电器停止（输出低电平）
void app_fm_stop(void)
{
    HAL_GPIO_WritePin(app_fm_gpio_port, app_fm_pin, GPIO_PIN_RESET);
}

/***
 * USART USB Sync
 */
#include "drv_usart.h"
#include "usb_device.h"
#include "usb_midi.h"
#include "app_msg.h"
#include "sys_manager.h"

/* 发送队列处理 */
void app_handle_tx_queue(void)
{
    // 串口发送优先级列表 - 可以调整顺序来改变发送优先级
    // 当前顺序：UART2(MIDI) > UART1 > UART3
    // 建议MIDI串口优先，因为对时序要求严格
    const uint8_t uart_priority_list[] = {USART2_PORT, USART1_PORT, USART3_PORT};
    const uint8_t uart_count = sizeof(uart_priority_list) / sizeof(uart_priority_list[0]);
    
    bool dma_busy = 0;
    UART_HandleTypeDef *huart = NULL;
	UNUSED(huart);

    /* 按优先级列表遍历所有UART端口 */
    for (uint8_t i = 0; i < uart_count; i++)
    { 
        uint8_t port = uart_priority_list[i];
        
        switch (port)
        {
        case USART1_PORT:
            dma_busy = system_status.uart.uart1_dma_tx_busy;
            if(dma_busy)
            {
                if(system_status.uart.uart1_dma_tx_count++ >= 0xFFFF)
                {
                    system_status.uart.uart1_dma_tx_count = 0;
                    system_status.uart.uart1_dma_tx_busy = 0;
                }
            }
            huart = &huart1;
            break;
        case USART2_PORT:
            dma_busy = system_status.uart.uart2_dma_tx_busy;
            if(dma_busy)
            {
                if(system_status.uart.uart2_dma_tx_count++ >= 0xFFFF)
                {
                    system_status.uart.uart2_dma_tx_count = 0;
                    system_status.uart.uart2_dma_tx_busy = 0;
                }
            }
            huart = &huart2;
            break;
        case USART3_PORT:
            dma_busy = system_status.uart.uart3_dma_tx_busy;
            if(dma_busy)
            {
                if(system_status.uart.uart3_dma_tx_count++ >= 0xFFFF)
                {
                    system_status.uart.uart3_dma_tx_count = 0;
                    system_status.uart.uart3_dma_tx_busy = 0;
                }
            }
            huart = &huart3;
            break;
        }

        /* 临界区保护 */
        __disable_irq();
        bool is_busy = dma_busy;
        bool has_data = !app_msg_is_empty(&uart_tx_queues[port]);
        __enable_irq();

        /* 发送条件判断 */
        if (!is_busy && has_data)
        {
            app_msg_t *tx_msg = NULL;
            if (app_msg_dequeue(&uart_tx_queues[port], &tx_msg))
            {
                /* 实际发送操作，注意 tx_msg->len 为 uint8_t，可根据需要转换 */
                drv_usart_send_data((DRV_USART_PORT)port, tx_msg->data, tx_msg->len);
                /* 发送完后释放动态分配的消息内存 */
                app_msg_free(tx_msg);
            }
        }
    }
}

/*
 * 同步数据到各个目标端口
 * 参数说明：
 *   src  : 数据来源标识（用于判断不需要回送给自身）
 *   data : 待发送数据指针
 *   len  : 待发送数据长度（单位：字节）
 */
void app_sync_data(MessageSource src, uint8_t *data, uint16_t len)
{
    /* 限制数据长度，避免超过最大发送长度 */
    uint8_t tx_len = (len > UART_MSG_DATA_MAX_LEN) ? UART_MSG_DATA_MAX_LEN : (uint8_t)len;

    /* 逐渐测试数据直接发往串口1 */
    if (src == SRC_TRA_TEST)
    {
        drv_usart_send_data(USART1_PORT, data, len);
        return;
    }

    /* 若数据需要直接发往串口1（例如系统全发），则仅入队 USART1 TX 队列 */
    if (src == SRC_SYS_ALL)
    {
        if (!app_msg_enqueue(&uart_tx_queues[USART1_PORT], T_MSG_UART_TX_TYPE, data, tx_len))
        {
            /* 队列满处理，比如记录日志或丢弃数据 */
        }
        return;
    }
    
    /* 根据数据来源，分别同步到各 UART TX 队列 */
    if (src != SRC_UART1)
    {
        if (!app_msg_enqueue(&uart_tx_queues[USART1_PORT], T_MSG_UART_TX_TYPE, data, tx_len))
        {
            /* 处理 USART1 队列满情况 */
        }
    }
    
    if (src != SRC_UART2)
    {
        if (!app_msg_enqueue(&uart_tx_queues[USART2_PORT], T_MSG_UART_TX_TYPE, data, tx_len))
        {
            /* 处理 USART2 队列满情况 */
        }
    }
    
    if (src != SRC_UART3)
    {
        if (!app_msg_enqueue(&uart_tx_queues[USART3_PORT], T_MSG_UART_TX_TYPE, data, tx_len))
        {
            /* 处理 USART3 队列满情况 */
        }
    }
    
    /* 同步到 USB，直接调用 USB 发送函数（USB 不使用消息队列） */
    if (src != SRC_USB)
    {
        USB_HID_Send(data, len);
    }
        
}
